// 指定GLSL版本为OpenGL ES 3.0
#version 300 es

// 设置高精度浮点数
precision highp float;

// 统一变量（由外部传入的常量）
uniform vec2 uWindowSize;   // 窗口尺寸（像素）
uniform vec2 uTexSize;      // 纹理尺寸（像素）
uniform float uSigma;       // 空间域高斯核的标准差
uniform float uBSigma;      // 颜色域高斯核的标准差
uniform sampler2D uTex;     // 输入纹理采样器

// 输入变量（从顶点着色器传入）
in vec2 vTexCoord;         // 当前片元的纹理坐标（标准化0-1）

// 输出变量
out vec4 color;            // 最终输出的颜色值（RGBA）

// 定义滤波器核大小（必须是奇数）
#define MSIZE 32

/**
 * 一维高斯分布概率密度函数
 * @param x 输入值
 * @param sigma 标准差
 * @return 高斯分布概率密度
 */
float normpdf(in float x, in float sigma) {
  return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma;
}

/**
 * 三维高斯分布概率密度函数（用于颜色空间）
 * @param v 输入向量（通常表示颜色差异）
 * @param sigma 标准差
 * @return 高斯分布概率密度
 */
float normpdf3(in vec3 v, in float sigma) {
  return 0.39894 * exp(-0.5 * dot(v, v) / (sigma * sigma)) / sigma;
}

/**
 * 双边滤波函数
 * @param tex 输入纹理
 * @return 滤波后的颜色值
 */
vec4 bilateralBlur(sampler2D tex) {
  // 获取当前像素颜色
  vec4 textureData = texture(tex, vTexCoord);
  vec3 c = textureData.xyz;
  
  // 计算核半径
  int kSize = (MSIZE - 1) / 2;
  float kernel[MSIZE];  // 高斯核数组
  vec3 final_colour = vec3(0.0);  // 最终颜色

  // 创建1D高斯核
  float Z = 0.0;  // 归一化因子
  for (int j = 0; j <= kSize; ++j) {
    // 利用对称性同时设置左右两侧的核权重
    kernel[kSize + j] = kernel[kSize - j] = normpdf(float(j), uSigma);
  }

  // 双边滤波参数
  vec3 cc;  // 邻域像素颜色
  float factor;  // 组合权重因子
  float bZ = 1.0 / normpdf(0.0, uBSigma);  // 颜色域归一化因子

  // 遍历邻域像素
  for (int i = -kSize; i <= kSize; ++i) {
    for (int j = -kSize; j <= kSize; ++j) {
      // 获取邻域像素颜色
      cc = texture(tex, (gl_FragCoord.xy + vec2(float(i), float(j))) / uTexSize).rgb;
      
      // 计算组合权重：空间权重 * 颜色相似度权重
      factor = normpdf3(cc - c, uBSigma) * bZ * kernel[kSize + j] * kernel[kSize + i];
      
      // 累加归一化因子和加权颜色
      Z += factor;
      final_colour += factor * cc;
    }
  }

  // 返回归一化后的颜色，保留原始alpha通道
  return vec4(final_colour / Z, textureData.w);
}

/**
 * 高斯模糊函数（当前未使用）
 * @param tex 输入纹理
 * @return 模糊后的颜色值
 */
vec4 gaussianBlur(sampler2D tex) {
  // 预定义的偏移和权重（优化过的5x5高斯核）
  const float offset[3] = float[](0.0, 1.3846153846, 3.2307692308);
  const float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703);
  
  // 中心像素贡献
  vec4 textureData = texture(tex, vTexCoord);
  vec4 c = vec4(textureData.xyz * weight[0], textureData.w);

  // 垂直方向模糊（上下对称采样）
  for (int i=1; i<3; i++) {
    c.xyz += texture(tex, (vec2(gl_FragCoord) + vec2(0.0, offset[i])) / uTexSize).xyz * weight[i];
    c.xyz += texture(tex, (vec2(gl_FragCoord) - vec2(0.0, offset[i])) / uTexSize).xyz * weight[i];
  }

  return c;
}

void main() {
  // 应用双边滤波并输出结果
  color = bilateralBlur(uTex);
}